package crystal.workshop.analysis;

import java.util.Vector;

import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;

import crystal.workshop.ui.StructuresListModel;

public class Analysis {
	
	class AnalysisEventHandler implements ListDataListener {
		
		@Override
		public void contentsChanged(ListDataEvent e) {
			
		}
		
		@Override
		public void intervalAdded(ListDataEvent e) { 
			if(e.getSource() == Analysis.this.strListModel)
				structuresAdded(e.getIndex0(), e.getIndex1());
		}
		
		@Override
		public void intervalRemoved(ListDataEvent e) { 
			if(e.getSource() == Analysis.this.strListModel)
				structuresRemoved(e.getIndex0(), e.getIndex1());
		}
	}
	
	protected StructuresListModel strListModel;
	
	protected AnalysisEventHandler eventHandler;

	protected Vector<PropertiesCalculator> propertiesCalculators = new Vector<PropertiesCalculator>();
	
	public void addPropertiesCalculator(final PropertiesCalculator calculator) {
		propertiesCalculators.add(calculator);
		// TODO: Add properties to all structures.
	}
	
	public boolean removePropertiesCalculator(final PropertiesCalculator calculator) {
		boolean removed = false;
		if( propertiesCalculators.remove(calculator) ) {
			// TODO: Remove that property from all structures. 
			removed = true;
		}
		return removed;
	}
	
	protected void structuresAdded(final int index0, final int index1) {
		final int start = Math.min(index0, index1);
		final int end = Math.max(index0, index0);
		for(int i = start; i <= end; ++i) {
			calculateAllPropertiesForStructure(i);
		}
	}
	
	protected void structuresRemoved(final int index0, final int index1) {
		final int start = Math.min(index0, index1);
		final int end = Math.max(index0, index0);
		for(int i = start; i <= end; ++i) {
			removeAllPropertiesForStructure(i);
		}
	}
	
	/**
	 * Apply all property calculators to this structure
	 * @param index the index of the structure in the structure list
	 */
	protected void calculateAllPropertiesForStructure(final int index) {
		for(PropertiesCalculator calc : propertiesCalculators) {
			calc.calculateProperties(strListModel.getStructure(index));
		}
	}
	
	/**
	 * Remove all properties from this structure
	 * @param index the index of the structure in the structure list
	 */
	protected void removeAllPropertiesForStructure(final int index) {
		for(PropertiesCalculator calc : propertiesCalculators) {
			calc.removeProperties(strListModel.getStructure(index));
		}
	}
	
	/**
	 * Return the structure list model.
	 * @return the structures list model.
	 */
	protected StructuresListModel getStructuresListModel() {
		return strListModel;
	}
	
	/**
	 * Set the the structure list model to a new value.
	 * @param newValue the new structure list model
	 */
	public void setStructureListModel(final StructuresListModel newValue) {
		if (strListModel != newValue) {
			try {
				/* Stop listening for events from the current object */
				if (strListModel != null) {
					strListModel.removeListDataListener(eventHandler);
				}
				strListModel = newValue;
	
				/* Listen for events from the new object */
				if (strListModel != null) {
					strListModel.addListDataListener(eventHandler);
				}
			} catch (Exception e) {
			}
		};
	}
}
